<?php
namespace app\api\services;

use app\common\libs\Singleton;

class UserLevelService
{
    use Singleton;

    /**
     * 检查用户是否可以升级
     * @param  [type] $userId [description]
     * @return [type]         [description]
     */
    public function checkUpgrade($userId)
    {
        $level = \think\facade\Db::table('member')
            ->where('id', $userId)
            ->value('level');

        $maxLevel = \think\facade\Db::table('base_user_upgrade')
            ->where('status', 1)
            ->max('number');
        if ($level >= $maxLevel) {
            \think\facade\Log::info(json_encode([
                'userId'   => $userId,
                'level'    => $level,
                'maxLevel' => $maxLevel,
                'msg'      => '已经是最大用户等级，不需要升级',
            ], 320));
            return true;
        }

        $upToLevelArr = [];
        // 只需要检查到 level的上一级
        for ($i = $maxLevel; $i > $level; $i--) {
            [$doUp, $next, $option] = $this->checkNext($userId, $i);
            // echo "$i, {$doUp}), " . json_encode($option) . "\n";
            if ($doUp) {
                $this->doUpgrade($userId, $i, $next, $option);
                break;
            }
        }
        // var_export([
        //     'userId'   => $userId,
        //     'level'    => $level,
        //     'maxLevel' => $maxLevel,
        //     'option'   => $option,
        //     'next'     => $next,
        //     'doUp'     => $doUp,
        // ]);
        // exit;
        return true;
    }

    private function getCheckItems($next)
    {
        return [
            'goods_vip_status'      => $next['goods_vip_status'], // 购买入会礼包
            'goods_status'          => $next['goods_status'], // 购买任一指定商品
            'teams_direct_status'   => $next['teams_direct_status'], // 直推团队 N 人
            'teams_indirect_status' => $next['teams_indirect_status'], // 间接团队 N 人
            'teams_users_status'    => $next['teams_users_status'], // 团队总数 N 人
            'order_amount_status'   => $next['order_amount_status'], // 订单总额
            'order_count_status'    => $next['order_count_status'], // 订单数量
        ];
    }

    private function checkNext($userId, $level)
    {
        $next = \think\facade\Db::table('base_user_upgrade')
            ->where('number', $level)
            ->where('status', 1)
            ->find();
        if (empty($next)) {
            return [false, $next, []];
        }

        // $goods_vip_status      = $next['goods_vip_status']; // 购买入会礼包
        // $goods_status          = $next['goods_status']; // 购买任一指定商品
        // $teams_direct_status   = $next['teams_direct_status']; // 直推团队 N 人
        // $teams_indirect_status = $next['teams_indirect_status']; // 间接团队 N 人
        // $teams_users_status    = $next['teams_users_status']; // 团队总数 N 人
        // $order_amount_status   = $next['order_amount_status']; // 订单总额
        // $order_count_status    = $next['order_count_status']; // 订单数量
        $checkItems = $this->getCheckItems($next);

        $doUp = false;
        // 会员升级规则(0单个,1同时) 1=>'达成所有升级条件',0=>'达成任何升级条件'
        $upgrade_type = $next['upgrade_type'];

        $option = [
            'upgrade_type' => $upgrade_type,
            'checkItems'   => $checkItems,
        ];
        if ($upgrade_type == 0) {
            foreach ($checkItems as $k => $v) {
                if ($v) {
                    $doUp           = $this->$k($userId, $level, $next);
                    $option['k']    = $k;
                    $option['v']    = $v;
                    $option['doUp'] = $doUp;
                    if ($doUp) {
                        break;
                    }
                }
            }
        } elseif ($upgrade_type == 1) {
            $res = [];
            foreach ($checkItems as $k => $v) {
                if ($v) {
                    $res[] = $this->$k($userId, $level, $next);
                }
            }
            $option['upgrade_items'] = $res;
            // $res 数组中所有元素都为 true，array_product 将返回 1 否在返回 0
            $doUp = array_product($res) === 1;
        }
        return [$doUp, $next, $option];
    }

    /**
     * 需要购买入会礼包
     * @param string $value [description]
     */
    private function goods_vip_status($userId, $level, $next)
    {
        $id = \think\facade\Db::table('packs')
            ->where('deleted', 0)
            ->where('status', 1)
            ->where('give_member_level', $next['number'])
            ->value('id');
        // var_dump($id, $next['number']);exit;
        $count = \think\facade\Db::table('packs_order')
            ->where('deleted', 0)
        // 状态 0待支付 1待发货 2待收货 3已完成 4取消
            ->whereIn('status', [1, 2, 3])
            ->where('packs_id', $id)
            ->where('member_id', $userId)
            ->count();
        // var_dump($count);
        // echo \think\facade\Db::table('packs_order')->getlastsql();exit;
        return $count > 0 ? true : false;
    }

    /**
     * 购买任一指定商品
     * @param string $value [description]
     */
    private function goods_status($userId, $level, $next)
    {
        $buy_goods_ids = empty($next['buy_goods_ids']) ? [] : json_decode($next['buy_goods_ids'], true);
        $buy_goods_ids = $buy_goods_ids['only_one'] ?? [];
        if (empty($buy_goods_ids)) {
            return false;
        }

        // 选择非供应链产品，可多选，多选时，只需要买其中一个产品即可;
        $count = \think\facade\Db::table('order_goods')
            ->where('deleted', 0)
        // 状态 0待支付 1待发货 2待收款 3已收货 4已完成 5退款中 6退款成功  7取消 8超时取消 9待退货
            ->whereIn('status', [3, 4])
        // 1 线下直付单 2线上单 3线下单 4供应链
            ->whereIn('order_type', [1, 2, 3])
            ->whereIn('goods_id', $buy_goods_ids)
            ->where('user_id', $userId)
            ->count();
        return $count > 0 ? true : false;
    }

    /**
     * 直推团队 N 人
     * @param string $value [description]
     */
    private function teams_direct_status($userId, $level, $next)
    {
        $count = \think\facade\Db::table('member')
            ->where('deleted', 0)
            ->where('status', 1)
            ->where('invite_id', $userId)
            ->count();
        return $count >= $next['teams_direct_number'] ? true : false;
    }
    /**
     * 间接团队 N 人
     * @param string $value [description]
     */
    private function teams_indirect_status($userId, $level, $next)
    {
        $count = \think\facade\Db::table('member')
            ->where('deleted', 0)
            ->where('status', 1)
            ->where('invite_third_id', $userId)
            ->count();
        return $count >= $next['teams_indirect_number'] ? true : false;
    }

    /**
     * 团队总数 N 人 （只包含直推+间推）
     * @param string $value [description]
     */
    private function teams_users_status($userId, $level, $next)
    {
        $count = \think\facade\Db::table('member')
            ->where('deleted', 0)
            ->where('status', 1)
        // ->where('invite_ids', 'like', '%-' . $userId . '-%') // 无限极
            ->where('invite_id|invite_third_id', $userId)
            ->count();
        // echo \think\facade\Db::table('member')->getLastSql();
        // var_dump($count);exit;
        return $count >= $next['teams_users_number'] ? true : false;
    }

    /**
     * 获取用户直推+间推用户ID
     * @param  [type] $userId [description]
     * @return [type]         [description]
     */
    private function teams_user_ids($userId)
    {
        $ids = \think\facade\Db::table('member')
            ->where('deleted', 0)
            ->where('status', 1)
            ->where('invite_third_id|invite_id', $userId)
            ->column('id');
        // echo \think\facade\Db::table('member')->getlastsql();
        // echo "\n";
        // var_dump($ids);exit;
        return (array) $ids;
    }
    /**
     * 订单总额 按订单实际支付金额计算，订单完成确认收货计算金额
     * @param string $value [description]
     */
    private function order_amount_status($userId, $level, $next)
    {
        // “团队计数”
        // 1 “参与”时，就需要（直推+间推+自己的） “订单数量或者金额”达到特定的数量；
        // 2 不参与时，自己的 “订单数量或者金额”达到特定的数量；
        // var_dump($next['upgrade_team']);exit;
        if ($next['upgrade_team'] == 1) {
            $ids     = $this->teams_user_ids($userId);
            $ids[]   = $userId;
            $userIds = $ids;
        } else {
            $userIds = [$userId];
        }
        $sum = \think\facade\Db::table('order')
            ->where('deleted', 0)
        // 0待支付 1待发货 2待收货 3已收货 4已完成 5退款中 6退款成功 7取消 8超时取消 9待退货
            ->whereIn('status', [3, 4])
        // 1 线下直付单 2线上单 3线下单 4供应链
        // ->whereIn('order_type', [1, 2, 3])
            ->whereIn('user_id', $userIds)
            ->sum('pay_price');
        // echo \think\facade\Db::table('order')->getlastsql();
        // echo "\n";
        // var_dump($sum);exit;
        return $sum >= $next['order_amount_number'] ? true : false;
    }

    /**
     * 订单数量 按完成订单计算
     * @param string $value [description]
     */
    private function order_count_status($userId, $level, $next)
    {
        // “团队计数”
        // 1 “参与”时，就需要（直推+间推+自己的） “订单数量或者金额”达到特定的数量；
        // 2 不参与时，自己的 “订单数量或者金额”达到特定的数量；
        // var_dump($next['upgrade_team']);exit;
        if ($next['upgrade_team'] == 1) {
            $ids     = $this->teams_user_ids($userId);
            $ids[]   = $userId;
            $userIds = $ids;
        } else {
            $userIds = [$userId];
        }
        $count = \think\facade\Db::table('order')
            ->where('deleted', 0)
        // 0待支付 1待发货 2待收货 3已收货 4已完成 5退款中 6退款成功 7取消 8超时取消 9待退货
            ->whereIn('status', [3, 4])
        // 1 线下直付单 2线上单 3线下单 4供应链
        // ->whereIn('order_type', [1, 2, 3])
            ->whereIn('user_id', $userIds)
            ->count();
        return $count >= $next['order_count_number'] ? true : false;
    }

    /**
     * 用户满足升级条件，执行升级
     * @param  [type] $user  [description]
     * @param  [type] $level [description]
     * @param  [type] $next  [description]
     * @return [type]        [description]
     */
    private function doUpgrade($userId, $level, $next, $option = [])
    {
        // var_dump($userId, $level, $option);
        // 启动事务
        $reward_rule = empty($next['reward_rule']) ? [] : json_decode($next['reward_rule'], true);

        $gxz           = $reward_rule['gxz'] ?? 0;
        $gxz_status    = $reward_rule['gxz_status'] ?? 0;
        $coupon_status = $reward_rule['coupon_status'] ?? 0;
        $coupon_ids    = $reward_rule['coupon_ids'] ?? [];
        $coupon_list   = [];

        if ($coupon_status == 1 && ! empty($coupon_ids)) {
            $where = [
                ['status', '=', 1],
                ['deleted', '=', 0],
                // 使用场景:  10只能社区经营者使用'
                ['use_scene', '=', 0],
                ['id', 'in', $coupon_ids],
            ];
            $coupon_list = \app\common\models\Coupon::getInstance()
                ->where($where)
                ->select();
        }
        // var_dump($gxz, $coupon_ids);exit;
        \think\facade\Db::startTrans();
        try {
            if ($gxz_status == 1 && $gxz > 0) {
                $logType = 'user_level_upgrade';
                $msg     = '会员升级到【' . $next['name'] . '】，赠送贡献值';
                \app\api\services\MemberService::getInstance()->addFinanceLog(
                    $userId, $logType, $gxz, 7, $msg);
            }
            if ($coupon_status == 1 && ! empty($coupon_list)) {
                foreach ($coupon_list as $v) {
                    \app\api\services\CouponService::getInstance()->autoRelease($userId, $v);
                }
            }
            //
            \think\facade\Db::table('member')->where('id', $userId)
                ->update([
                    'level' => $next['number'],
                ]);
            \think\facade\Db::table('base_user_upgrade_log')->insert([
                'user_id'       => $userId,
                'from_level'    => $level,
                'to_level'      => $next['number'],
                'to_level_data' => json_encode($next, 320),
                'extends'       => json_encode($option, 320),
            ]);
            // 提交事务
            \think\facade\Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            \think\facade\Db::rollback();
            $error = '操作失败 ' . $e->getMessage();
            \think\facade\Log::error(json_encode([
                'userId' => $userId,
                'level'  => $level,
                // 'next'   => $next,
                'error'  => $error,
                'trace'  => $e->getTrace(),
            ], 320));
            return false;
        }
        return true;
    }

    /**
     * 获取用户等级折扣率
     * @param  [type] $uid [description]
     * @return [type]     float [0, 1)
     */
    public function levelDiscount($uid)
    {
        $level = \think\facade\Db::table('member')
            ->where('id', $uid)
            ->value('level');
        if (empty($level)) {
            return [0, 1];
        }

        $reward_rule = \think\facade\Db::table('base_user_upgrade')
            ->where('number', $level)
            ->value('reward_rule');
        $reward_rule          = empty($reward_rule) ? [] : json_decode($reward_rule, true);
        $discount_status      = $reward_rule['discount_status'] ?? 0;
        $coupon_discount_both = $reward_rule['coupon_discount_both'] ?? 0;
        if ($discount_status != 1) {
            return [0, 1];
        }
        $discount = $reward_rule['discount'] ?? 0;
        $discount = $discount > 0 && $discount <= 9.9 ? $discount : 0;

        return [$discount / 10, $coupon_discount_both];
    }
}
